﻿using Core.DeviceProtocol;
using System;
using System.Collections.Generic;
using System.Linq;
using Core.Model;
using Core.Msg;
using System.Text;
using Core.ChannelProtocol;

namespace DLT645
{
    public class Dlt645Protocol : BaseDevProtocol
    {
        private readonly List<Dlt645Command> _sendFrame = new List<Dlt645Command>();
        private int _sendIndex = -1;
        private Dlt645Command _modItem;

        private Dlt645DataMap _dlt645DataMap;

        public override bool Initialize(BaseChannel channel, Device dev, List<Operation> operations, List<DataItem> dataItems)
        {
            base.Initialize(channel, dev, operations, dataItems);
            _modItem = new Dlt645Command(Dev.ChannelId, Dev.Id,"普通报文");
            _dlt645DataMap = new Dlt645DataMap(base.DataItems);
            try
            {
                return InitSendInfo();
            }
            catch (Exception e)
            {
                MsgLog(true, "初始化轮询命令出错:" + e.Message);
            }
            return true;
        }
        public override List<DataItem> GetInitDataItems(Device dev)
        {
            return Dlt645DataMap.GetDataItems(dev);
        }
        /// <summary>
        /// 轮询函数
        /// </summary>
        /// <returns></returns>
        public override bool RunPolling()
        {
            if (_sendFrame == null || _sendFrame.Count == 0) return false;
            _sendIndex++;
            if (_sendIndex < 0 || _sendIndex >= _sendFrame.Count) _sendIndex = 0;

            _modItem = _sendFrame[_sendIndex];
            if (_modItem!=null)
            {
                this.Channel.PutCommand(_modItem);
            }
            else
            {
                return false;
            }
            return true;
        }
        protected virtual bool InitSendInfo()
        {
            _sendFrame.Clear();
            if(_dlt645DataMap.Ua>=0 || _dlt645DataMap.Ub>=0 || _dlt645DataMap.Uc>=0) // 存在该项
                _sendFrame.Add(this.ReadVoltage(this.Dev)); // 读电压 3
            if (_dlt645DataMap.Ia >= 0 || _dlt645DataMap.Ib >= 0 || _dlt645DataMap.Ic >= 0)
                _sendFrame.Add(this.ReadCurrent(this.Dev)); // 读电流 3
            if (_dlt645DataMap.Psum >= 0 || _dlt645DataMap.Pa >= 0 || _dlt645DataMap.Pb >= 0 || _dlt645DataMap.Pc >= 0)
                _sendFrame.Add(this.ReadInstantPowerkW(this.Dev)); // 瞬时有功功率 4
            if (_dlt645DataMap.Qsum >= 0 || _dlt645DataMap.Qa >= 0 || _dlt645DataMap.Qb >= 0 || _dlt645DataMap.Qc >= 0)
                _sendFrame.Add(this.ReadInstantPowerkVar(this.Dev)); // 瞬时无功功率 4
            if (_dlt645DataMap.Ssum >= 0 || _dlt645DataMap.Sa >= 0 || _dlt645DataMap.Sb >= 0 || _dlt645DataMap.Sc >= 0)
                _sendFrame.Add(this.ReadInstantPowerKva(this.Dev)); // 瞬时视在功率 4
            //_sendFrame.Add(this.ReadCurPowerNeedkVar(this.Dev)); // 当前无功功率 4
            //_sendFrame.Add(this.ReadCurPowerNeedKva(this.Dev)); // 当前视在功率 4
            //_sendFrame.Add(this.ReadCurPowerNeedkW(this.Dev));     // 读当前有功需量 1
            //_sendFrame.Add(this.ReadCurPowerNeedkVar(this.Dev));   // 读当前无功需量 1
            //_sendFrame.Add(this.ReadCurPowerNeedKva(this.Dev));    // 读当前视在需量 1
            if (_dlt645DataMap.Freq >= 0)
                _sendFrame.Add(this.ReadFrequency(this.Dev)); // 电网频率 1
            if (_dlt645DataMap.Cap >= 0 || _dlt645DataMap.Cap1 >= 0 || _dlt645DataMap.Cap2 >= 0 || _dlt645DataMap.Cap3 >= 0 || _dlt645DataMap.Cap4 >= 0)
                _sendFrame.Add(this.ReadTotalkWh(this.Dev));  // 组合有功总电能 5
            if (_dlt645DataMap.PFsum >= 0 || _dlt645DataMap.PFa >= 0 || _dlt645DataMap.PFb >= 0 || _dlt645DataMap.PFc >= 0)
                _sendFrame.Add(this.ReadInstantPowerFactor(this.Dev)); // 瞬时功率因数 4
            if (_dlt645DataMap.MeterTime >= 0)
                _sendFrame.Add(this.ReadTime(this.Dev)); // 时间 1
            if (_dlt645DataMap.MeterDate >= 0)
                _sendFrame.Add(this.ReadDate(this.Dev));  // 日期 1
            return true;
        }

        public static byte[] ByteMinus33(byte[] bytesIn)
        {
            if (bytesIn == null || bytesIn.Length == 0)
            {
                return null;
            }
            byte[] byteConvert = new byte[bytesIn.Length];
            for (int i = 0; i < bytesIn.Length; i++)
            {
                byteConvert[i] = (byte)(bytesIn[i] - 0x33);
            }
            return byteConvert;
        }
        public static byte[] BytePlus33(byte[] bytesIn)
        {
            if (bytesIn == null || bytesIn.Length == 0)
            {
                return null;
            }
            byte[] byteConvert = new byte[bytesIn.Length];
            for (int i = 0; i < bytesIn.Length; i++)
            {
                byteConvert[i] = (byte)(bytesIn[i] + 0x33);
            }
            return byteConvert;
        }
        /// <summary>
        /// 字节数组转BCD码(低位在前)
        /// </summary>
        /// <param name="byData">字节数组</param>
        /// <param name="start">起始字节</param>
        /// <param name="cnt">字节数</param>
        /// <returns></returns>
        public static UInt64 BytesToBcd(byte[] byData, int start, int cnt)
        {
            if (byData == null || byData.Length < start + cnt)
            {
                return 0;
            }
            UInt64 resData = 0;
            StringBuilder bytestr = new StringBuilder();
            for (int i = cnt + start - 1; i >= start; i--)  // 调转wei高位在前
            {
                bytestr.Append(string.Format("{0:X2}", byData[i] - 0x33));  // 减去0x33
            }
            try
            {
                resData = UInt64.Parse(bytestr.ToString());
            }
            catch
            {
            }
            return resData;
        }
        /// <summary>
        /// 转为带符号位的BCD码
        /// </summary>
        /// <param name="byData"></param>
        /// <param name="start"></param>
        /// <param name="cnt"></param>
        /// <returns></returns>
        public static Int64 BytesToBcdWithFlag(byte[] byData, int start, int cnt)
        {
            if (byData == null || byData.Length < start + cnt)
            {
                return 0;
            }
            int flag = 1;
            UInt64 resData = 0;
            StringBuilder bytestr = new StringBuilder();
            for (int i = cnt + start - 1; i >= start; i--)  // 调转为高位在前
            {
                if (i == cnt + start - 1)
                {
                    if (((byData[i] - 0x33) & 0x80) > 1)
                    {
                        flag = -1;
                    }
                    bytestr.Append(string.Format("{0:X2}", (byData[i] - 0x33) & 0x7F));  // 减去0x33
                }
                else
                {
                    bytestr.Append(string.Format("{0:X2}", byData[i] - 0x33));  // 减去0x33
                }
            }
            try
            {
                resData = UInt64.Parse(bytestr.ToString());
            }
            catch
            {
            }

            return (Int64)resData * flag;
        }
        /// <summary>
        /// BCD转字节
        /// </summary>
        /// <param name="bcdData">源数据</param>
        /// <param name="byLength">BCD码的个数</param>
        /// <returns></returns>
        public static byte[] BcdToBytes(UInt64 bcdData, int byLength)
        {
            List<byte> bcdbytes = new List<byte>();

            StringBuilder strData = new StringBuilder(bcdData.ToString(string.Format("X{0}", byLength)));
            byte temp;
            for (int i = 0; i < byLength / 2; i++)
            {
                temp = (byte)((byte)(Convert.ToByte(strData[2 * i].ToString(), 10) << 4) + Convert.ToByte(strData[2 * i + 1].ToString(), 10));
                bcdbytes.Add((byte)(0x33 + temp));
            }
            return bcdbytes.ToArray();
        }
        /// <summary>
        /// 校准数据转字节
        /// </summary>
        /// <param name="bcdData"></param>
        /// <param name="byLength">字节个数</param>
        /// <returns></returns>
        public static byte[] CaliDataToBytes(UInt64 bcdData, int byLength)
        {
            byte[] databytes = BitConverter.GetBytes(bcdData);
            byte[] tagetBytes = new byte[byLength];
            Buffer.BlockCopy(databytes, 0, tagetBytes, 0, byLength);
            //for (int i = 0; i < byLength; i++)
            //{
            //    tagetBytes[i] += 0x33;
            //}
            return tagetBytes;
        }
        /// <summary>
        /// 打包发送数据
        /// </summary>
        /// <param name="addr"></param>
        /// <param name="dataid"></param>
        /// <param name="ctrlCode"></param>
        /// <param name="writedata"></param>
        /// <returns></returns>
        public static byte[] MakePacket(UInt64 addr, UInt32 dataid, byte ctrlCode, byte[] writedata)
        {
            List<byte> sendList = new List<byte>();

            //sendList.AddRange(new byte[] { 0xFE, 0xFE, 0xFE, 0xFE });   // 前置符
            sendList.Add(0x68); // 起始符
            sendList.AddRange(BcdToBytes(addr, 12));     // 地址
            sendList.Add(0x68); // 起始符
            sendList.Add(ctrlCode); // 控制码
            if (writedata == null)
            {
                sendList.Add(4);
                sendList.AddRange(BcdToBytes(dataid, 4));     // 数据标识
            }
            else
            {
                sendList.Add((byte)(4 + writedata.Length));
                sendList.AddRange(BcdToBytes(dataid, 4));     // 数据标识
                sendList.AddRange(writedata); // 权限密码 操作者代码  写数据
            }
            byte sum = 0;
            foreach (var item in sendList)
            {
                sum += item;
            }
            sendList.Add(sum);
            sendList.Add(0x16);

            return sendList.ToArray();
        }
        /// <summary>
        /// 帧结构转字节数组
        /// </summary>
        /// <param name="frameIn"></param>
        /// <returns></returns>
        public static byte[] FrameToBuffer(dlt645Frame frameIn)
        {
            UInt64 addr = frameIn.Address;
            UInt32 dataid = frameIn.DataID;
            byte ctrlCode = frameIn.CtrlCode;

            List<byte> sendList = new List<byte>();
            //sendList.AddRange(new byte[] { 0xFE, 0xFE, 0xFE, 0xFE });   // 前置符
            sendList.Add(0x68); // 起始符
            byte[] addrbys = new byte[6];
            byte[] addrg = BitConverter.GetBytes(addr);
            for (int i = 0; i < 6; i++)
            {
                addrbys[i] = addrg[i];
            }
            sendList.AddRange(addrbys); // 地址BCDToBytes(addr, 12)
            sendList.Add(0x68); // 起始符
            sendList.Add(ctrlCode); // 控制码
            sendList.Add(0);  // SendList[13]
            if (frameIn.NeedDataID)
            {
                sendList.AddRange(BytePlus33(BitConverter.GetBytes(dataid)));     // 数据标识
                sendList[13] += 4;
            }
            List<byte> writebytes = new List<byte>();
            if (frameIn.NeedPassword)
            {
                writebytes.AddRange(BcdToBytes(0x02, 2)); // 密码权限
                writebytes.AddRange(BcdToBytes(frameIn.PassWord, 6));
            }
            if (frameIn.NeedOperCode)
            {
                writebytes.AddRange(BcdToBytes(frameIn.OperCode, 8));
            }
            if (frameIn.WriteData != null && frameIn.WriteData.Length > 0)
            {
                writebytes.AddRange(BytePlus33(frameIn.WriteData));
            }
            if (writebytes.Count > 0)
            {
                sendList.AddRange(writebytes.ToArray());
                sendList[13] += (byte)writebytes.Count;
            }

            byte sum = 0;
            for (int i = 4; i < sendList.Count; i++)
            {
                sum += sendList[i];
            }
            sendList.Add(sum);
            sendList.Add(0x16);

            return sendList.ToArray();
        }

        /// <summary>
        /// 检查数据帧（出错时返回NULL）
        /// </summary>
        /// <param name="bufferIn"></param>
        /// <returns></returns>
        public static dlt645Frame BufferToFrame(byte[] bufferIn)
        {
            if (bufferIn == null || bufferIn.Length < 12) // 最短的帧为16字节
            {
                return null;
            }
            dlt645Frame frame = new dlt645Frame();
            int offset = 0;
            List<byte> bufferList = new List<byte>();
            bufferList.AddRange(bufferIn);

            // 检查前导符0xFE
            //while (offset < bufferList.Count - 1 && bufferList[offset] == 0xFE)
            //{
            //    offset++;
            //}
            //if (offset != 4)
            //{
            //    return null;
            //}
            // 检查起始符0x68
            if (bufferList[0] != 0x68 || bufferList[7] != 0x68)
            {
                return null;
            }
            else
            {
                byte[] byAddr = new byte[8];
                Buffer.BlockCopy(bufferIn, 1, byAddr, 0, 6);
                frame.Address = BitConverter.ToUInt64(byAddr, 0);
            }
            frame.CtrlCode = bufferList[8];
            frame.RecData = new byte[bufferIn.Length - 2 - 10];
            Buffer.BlockCopy(bufferIn, 10, frame.RecData, 0, bufferIn.Length - 2 - 10);
            //frame.DataID = (UInt32)BytesToBCD(BufferIn, 14, 4);
            return frame;
        }
        /// <summary>
        /// 读通信地址
        /// </summary>
        /// <returns></returns>
        public Dlt645Command ReadAddress1(Device dataCol)
        {
            Dlt645Command cmd = new Dlt645Command(dataCol.ChannelId,dataCol.Id, "读通信地址");
            cmd.Sendframe = new dlt645Frame(0xAAAAAAAAAAAA, 0x13);
            cmd.DealReceiveMsg = new EventHandler((rxcmd, y) =>
            {
                Dlt645Command rx = rxcmd as Dlt645Command;
                if (rx != null)
                {
                    dlt645Frame frame = BufferToFrame(rx.ReceiveBytes);
                    if (null != frame && frame.RecData != null && frame.RecData.Length >= 6)
                    {
                        List<byte> reclist = new List<byte>();
                        reclist.AddRange(ByteMinus33(frame.RecData));
                        reclist.Add(0x00);
                        reclist.Add(0x00);
                        dataCol.Address = BitConverter.ToUInt64(reclist.ToArray(), 0);
                        InitSendInfo();
                        rx.ReceiveResult = MsgResult.RecOk;
                    }
                    else
                    {
                        if (frame == null || frame.RecData == null)
                            rx.ReceiveResult =  MsgResult.RecTimeout;
                        else
                            rx.ReceiveResult = MsgResult.RecErr;
                    }
                }
            });
            return cmd;
        }
        /// <summary>
        /// 写通信地址
        /// </summary>
        /// <returns></returns>
        public Dlt645Command SetAddress1(Device dataCol, UInt64 addr)
        {
            Dlt645Command cmd = new Dlt645Command(dataCol.ChannelId,dataCol.Id, "写通信地址");
            cmd.Sendframe = new dlt645Frame(dataCol.Address, 0x04000401, 0x14, 0, 0x11111111, BitConverter.GetBytes(addr).Take(6).ToArray());
            //cmd.Sendframe = new dlt645Frame(dataCol.Address, 0x15, BitConverter.GetBytes(addr).Take(6).ToArray());
            cmd.DealReceiveMsg = new EventHandler((rxcmd, y) =>
            {
                Dlt645Command rx = rxcmd as Dlt645Command;
                if (rx != null)
                {
                    dlt645Frame frame = BufferToFrame(rx.ReceiveBytes);
                    if (null != frame && frame.CtrlCode == 0x94)
                    {
                        rx.ReceiveResult = MsgResult.RecOk;
                    }
                    else
                    {
                        if (frame == null || frame.RecData == null)
                            rx.ReceiveResult =  MsgResult.RecTimeout;
                        else
                            rx.ReceiveResult = MsgResult.RecErr;
                    }
                }
            });
            return cmd;
        }
        /// <summary>
        /// 读取仪表日期(年月日)
        /// </summary>
        /// <param name="dataCol"></param>
        /// <returns></returns>
        public Dlt645Command ReadDate(Device dataCol)
        {
            Dlt645Command cmd = new Dlt645Command(dataCol.ChannelId,dataCol.Id, "读仪表日期");
            cmd.Sendframe = new dlt645Frame(dataCol.Address, 0x04000101, 0x11);//dataCol.Address
            cmd.DealReceiveMsg = new EventHandler((rxcmd, y) =>
            {
                Dlt645Command rx = rxcmd as Dlt645Command;
                if (rx != null)
                {
                    dlt645Frame frame = BufferToFrame(rx.ReceiveBytes);
                    if (null != frame && frame.RecData.Length >= 8)
                    {
                        _dlt645DataMap.MeterDate = BytesToBcd(frame.RecData,4, 4);   // 仪表日期
                        rx.ReceiveResult = MsgResult.RecOk;
                    }
                    else
                    {
                        if (frame == null || frame.RecData == null)
                            rx.ReceiveResult =  MsgResult.RecTimeout;
                        else
                            rx.ReceiveResult = MsgResult.RecErr;
                    }
                }
            });
            return cmd;
        }
        /// <summary>
        /// 读取仪表时间(时分秒)
        /// </summary>
        /// <param name="dataCol"></param>
        /// <returns></returns>
        public Dlt645Command ReadTime(Device dataCol)
        {
            Dlt645Command cmd = new Dlt645Command(dataCol.ChannelId,dataCol.Id, "读仪表时间");
            cmd.Sendframe = new dlt645Frame(dataCol.Address, 0x04000102, 0x11);//dataCol.Address
            cmd.DealReceiveMsg = new EventHandler((rxcmd, y) =>
            {
                Dlt645Command rx = rxcmd as Dlt645Command;
                if (rx != null)
                {
                    dlt645Frame frame = BufferToFrame(rx.ReceiveBytes);
                    if (null != frame && frame.RecData.Length >= 7)
                    {
                        _dlt645DataMap.MeterTime = BytesToBcd(frame.RecData, 4, 3);   // 仪表时间
                        rx.ReceiveResult = MsgResult.RecOk;
                    }
                    else
                    {
                        if (frame == null || frame.RecData == null)
                            rx.ReceiveResult =  MsgResult.RecTimeout;
                        else
                            rx.ReceiveResult = MsgResult.RecErr;
                    }
                }
            });
            return cmd;
        }
        /// <summary>
        /// 读取组合有功电能
        /// </summary>
        /// <param name="dataCol">仪表数据集</param>
        /// <returns></returns>
        public Dlt645Command ReadTotalkWh(Device dataCol)
        {
            Dlt645Command cmd = new Dlt645Command(dataCol.ChannelId,dataCol.Id, "组合有功电能");
            cmd.Sendframe = new dlt645Frame(dataCol.Address, 0x0000FF00, 0x11);//dataCol.Address
            cmd.DealReceiveMsg = new EventHandler((rxcmd, y) =>
            {
                Dlt645Command rx = rxcmd as Dlt645Command;
                if (rx != null)
                {
                    dlt645Frame frame = BufferToFrame(rx.ReceiveBytes);
                    if (null != frame && frame.RecData.Length > 20)
                    {
                        _dlt645DataMap.Cap = 0.01f * BytesToBcd(frame.RecData, 4, 4);   // 组合有功总电量（Combined active power）
                        _dlt645DataMap.Cap1 = 0.01f * BytesToBcd(frame.RecData, 8, 4);    // 费率1
                        _dlt645DataMap.Cap2 = 0.01f * BytesToBcd(frame.RecData, 12, 4);   // 费率2
                        _dlt645DataMap.Cap3 = 0.01f * BytesToBcd(frame.RecData, 16, 4);   // 费率3
                        _dlt645DataMap.Cap4 = 0.01f * BytesToBcd(frame.RecData, 20, 4);   // 费率4

                        rx.ReceiveResult = MsgResult.RecOk;
                    }
                    else
                    {
                        if (frame == null || frame.RecData == null)
                            rx.ReceiveResult =  MsgResult.RecTimeout;
                        else
                            rx.ReceiveResult = MsgResult.RecErr;
                    }
                }
            });
            return cmd;
        }
        /// <summary>
        /// 读取正向有功电能
        /// </summary>
        /// <param name="dataCol">仪表数据集</param>
        /// <returns></returns>
        public Dlt645Command ReadForwardkWh(Device dataCol)
        {
            Dlt645Command cmd = new Dlt645Command(dataCol.ChannelId,dataCol.Id, "正向有功电能");
            cmd.Sendframe = new dlt645Frame(dataCol.Address, 0x0001FF00, 0x11);
            cmd.DealReceiveMsg = new EventHandler((rxcmd, y) =>
            {
                Dlt645Command rx = rxcmd as Dlt645Command;
                if (rx != null)
                {
                    dlt645Frame frame = BufferToFrame(rx.ReceiveBytes);
                    if (null != frame && frame.RecData.Length > 20)
                    {
                        //dataCol.Ppsum = 0.01f * BytesToBcd(frame.RecData, 4, 4);     // 正向有功总电量
                        //dataCol.Pp1 = 0.01f * BytesToBcd(frame.RecData, 8, 4);     // 费率1
                        //dataCol.Pp2 = 0.01f * BytesToBcd(frame.RecData, 12, 4);    // 费率2
                        //dataCol.Pp3 = 0.01f * BytesToBcd(frame.RecData, 16, 4);    // 费率3
                        //dataCol.Pp4 = 0.01f * BytesToBcd(frame.RecData, 20, 4);    // 费率4

                        rx.ReceiveResult = MsgResult.RecOk;
                    }
                    else
                    {
                        if (frame == null || frame.RecData == null)
                            rx.ReceiveResult =  MsgResult.RecTimeout;
                        else
                            rx.ReceiveResult = MsgResult.RecErr;
                    }
                }
            });
            return cmd;
        }
        /// <summary>
        /// 读取反向有功电能
        /// </summary>
        /// <param name="dataCol">仪表数据集</param>
        /// <returns></returns>
        public Dlt645Command ReadReversekWh(Device dataCol)
        {
            Dlt645Command cmd = new Dlt645Command(dataCol.ChannelId,dataCol.Id, "反向有功电能");
            cmd.Sendframe = new dlt645Frame(dataCol.Address, 0x0002FF00, 0x11);
            cmd.DealReceiveMsg = new EventHandler((rxcmd, y) =>
            {
                Dlt645Command rx = rxcmd as Dlt645Command;
                if (rx != null)
                {
                    dlt645Frame frame = BufferToFrame(rx.ReceiveBytes);
                    if (null != frame && frame.RecData.Length > 20)
                    {
                        //dataCol.Pnsum = 0.01f * BytesToBcd(frame.RecData, 4, 4);     // 反向有功总电量
                        //dataCol.Pn1 = 0.01f * BytesToBcd(frame.RecData, 8, 4);     // 费率1
                        //dataCol.Pn2 = 0.01f * BytesToBcd(frame.RecData, 12, 4);    // 费率2
                        //dataCol.Pn3 = 0.01f * BytesToBcd(frame.RecData, 16, 4);    // 费率3
                        //dataCol.Pn4 = 0.01f * BytesToBcd(frame.RecData, 20, 4);    // 费率4

                        rx.ReceiveResult = MsgResult.RecOk;
                    }
                    else
                    {
                        if (frame == null || frame.RecData == null)
                            rx.ReceiveResult =  MsgResult.RecTimeout;
                        else
                            rx.ReceiveResult = MsgResult.RecErr;
                    }
                }
            });
            return cmd;
        }

        /// <summary>
        /// 读取组合无功1电能
        /// </summary>
        /// <param name="dataCol">仪表数据集</param>
        /// <returns></returns>
        public Dlt645Command ReadGroupkkVarh1(Device dataCol)
        {
            Dlt645Command cmd = new Dlt645Command(dataCol.ChannelId,dataCol.Id, "组合无功1电能");
            cmd.Sendframe = new dlt645Frame(dataCol.Address, 0x0003FF00, 0x11);
            cmd.DealReceiveMsg = new EventHandler((rxcmd, y) =>
            {
                Dlt645Command rx = rxcmd as Dlt645Command;
                if (rx != null)
                {
                    dlt645Frame frame = BufferToFrame(rx.ReceiveBytes);
                    if (null != frame && frame.RecData.Length > 20)
                    {
                        //dataCol.Q = 0.01f * BytesToBcd(frame.RecData, 4, 4);     // 组合无功1总电能
                        //dataCol.SN00030001 = 0.01f * BytesToBcd(frame.RecData, 8, 4);     // 费率1
                        //dataCol.SN00030002 = 0.01f * BytesToBcd(frame.RecData, 12, 4);    // 费率2
                        //dataCol.SN00030003 = 0.01f * BytesToBcd(frame.RecData, 16, 4);    // 费率3
                        //dataCol.SN00030004 = 0.01f * BytesToBcd(frame.RecData, 20, 4);    // 费率4

                        rx.ReceiveResult = MsgResult.RecOk;
                    }
                    else
                    {
                        if (frame == null || frame.RecData == null)
                            rx.ReceiveResult =  MsgResult.RecTimeout;
                        else
                            rx.ReceiveResult = MsgResult.RecErr;
                    }
                }
            });
            return cmd;
        }
        /// <summary>
        /// 读取组合无功2电能
        /// </summary>
        /// <param name="dataCol">仪表数据集</param>
        /// <returns></returns>
        public Dlt645Command ReadGroupkkVarh2(Device dataCol)
        {
            Dlt645Command cmd = new Dlt645Command(dataCol.ChannelId,dataCol.Id, "组合无功2电能");
            cmd.Sendframe = new dlt645Frame(dataCol.Address, 0x0004FF00, 0x11);
            cmd.DealReceiveMsg = new EventHandler((Rxcmd, y) =>
            {
                Dlt645Command rx = Rxcmd as Dlt645Command;
                if (rx != null)
                {
                    dlt645Frame frame = BufferToFrame(rx.ReceiveBytes);
                    if (null != frame && frame.RecData.Length > 20)
                    {
                        //dataCol.SN00040000 = 0.01f * BytesToBCD(frame.RecData, 4, 4);     // 组合无功2总电能
                        //dataCol.SN00040001 = 0.01f * BytesToBCD(frame.RecData, 8, 4);     // 费率1
                        //dataCol.SN00040002 = 0.01f * BytesToBCD(frame.RecData, 12, 4);    // 费率2
                        //dataCol.SN00040003 = 0.01f * BytesToBCD(frame.RecData, 16, 4);    // 费率3
                        //dataCol.SN00040004 = 0.01f * BytesToBCD(frame.RecData, 20, 4);    // 费率4

                        rx.ReceiveResult = MsgResult.RecOk;
                    }
                    else
                    {
                        if (frame == null || frame.RecData == null)
                            rx.ReceiveResult =  MsgResult.RecTimeout;
                        else
                            rx.ReceiveResult = MsgResult.RecErr;
                    }
                }
            });
            return cmd;
        }
        /// <summary>
        /// 读取第一象限无功电能
        /// </summary>
        /// <param name="dataCol">仪表数据集</param>
        /// <returns></returns>
        public Dlt645Command ReadQuadrantIkVarh(Device dataCol)
        {
            Dlt645Command cmd = new Dlt645Command(dataCol.ChannelId,dataCol.Id, "第一象限无功电能");
            cmd.Sendframe = new dlt645Frame(dataCol.Address, 0x0005FF00, 0x11);
            cmd.DealReceiveMsg = new EventHandler((rxcmd, y) =>
            {
                Dlt645Command rx = rxcmd as Dlt645Command;
                if (rx != null)
                {
                    dlt645Frame frame = BufferToFrame(rx.ReceiveBytes);
                    if (null != frame && frame.RecData.Length > 20)
                    {
                        //dataCol.SN00050000 = 0.01f * BytesToBCD(frame.RecData, 4, 4);     // 第一象限无功电能
                        //dataCol.SN00050001 = 0.01f * BytesToBCD(frame.RecData, 8, 4);     // 费率1
                        //dataCol.SN00050002 = 0.01f * BytesToBCD(frame.RecData, 12, 4);    // 费率2
                        //dataCol.SN00050003 = 0.01f * BytesToBCD(frame.RecData, 16, 4);    // 费率3
                        //dataCol.SN00050004 = 0.01f * BytesToBCD(frame.RecData, 20, 4);    // 费率4

                        rx.ReceiveResult = MsgResult.RecOk;
                    }
                    else
                    {
                        if (frame == null || frame.RecData == null)
                            rx.ReceiveResult =  MsgResult.RecTimeout;
                        else
                            rx.ReceiveResult = MsgResult.RecErr;
                    }
                }
            });
            return cmd;
        }
        /// <summary>
        /// 读取第二象限无功电能
        /// </summary>
        /// <param name="dataCol">仪表数据集</param>
        /// <returns></returns>
        public Dlt645Command ReadQuadrantIIkVarh(Device dataCol)
        {
            Dlt645Command cmd = new Dlt645Command(dataCol.ChannelId,dataCol.Id, "第二象限无功电能");
            cmd.Sendframe = new dlt645Frame(dataCol.Address, 0x0006FF00, 0x11);
            cmd.DealReceiveMsg = new EventHandler((rxcmd, y) =>
            {
                Dlt645Command rx = rxcmd as Dlt645Command;
                if (rx != null)
                {
                    dlt645Frame frame = BufferToFrame(rx.ReceiveBytes);
                    if (null != frame && frame.RecData.Length > 20)
                    {
                        //dataCol.SN00060000 = 0.01f * BytesToBCD(frame.RecData, 4, 4);     // 第二象限无功电能
                        //dataCol.SN00060001 = 0.01f * BytesToBCD(frame.RecData, 8, 4);     // 费率1
                        //dataCol.SN00060002 = 0.01f * BytesToBCD(frame.RecData, 12, 4);    // 费率2
                        //dataCol.SN00060003 = 0.01f * BytesToBCD(frame.RecData, 16, 4);    // 费率3
                        //dataCol.SN00060004 = 0.01f * BytesToBCD(frame.RecData, 20, 4);    // 费率4

                        rx.ReceiveResult = MsgResult.RecOk;
                    }
                    else
                    {
                        if (frame == null || frame.RecData == null)
                            rx.ReceiveResult =  MsgResult.RecTimeout;
                        else
                            rx.ReceiveResult = MsgResult.RecErr;
                    }
                }
            });
            return cmd;
        }
        /// <summary>
        /// 读取第三象限无功电能
        /// </summary>
        /// <param name="dataCol">仪表数据集</param>
        /// <returns></returns>
        public Dlt645Command ReadQuadrantIIIkVarh(Device dataCol)
        {
            Dlt645Command cmd = new Dlt645Command(dataCol.ChannelId,dataCol.Id, "第三象限无功电能");
            cmd.Sendframe = new dlt645Frame(dataCol.Address, 0x0007FF00, 0x11);
            cmd.DealReceiveMsg = new EventHandler((Rxcmd, y) =>
            {
                Dlt645Command rx = Rxcmd as Dlt645Command;
                if (rx != null)
                {
                    dlt645Frame frame = BufferToFrame(rx.ReceiveBytes);
                    if (null != frame && frame.RecData.Length > 20)
                    {
                        //dataCol.SN00070000 = 0.01f * BytesToBCD(frame.RecData, 4, 4);     // 第三象限无功电能
                        //dataCol.SN00070001 = 0.01f * BytesToBCD(frame.RecData, 8, 4);     // 费率1
                        //dataCol.SN00070002 = 0.01f * BytesToBCD(frame.RecData, 12, 4);    // 费率2
                        //dataCol.SN00070003 = 0.01f * BytesToBCD(frame.RecData, 16, 4);    // 费率3
                        //dataCol.SN00070004 = 0.01f * BytesToBCD(frame.RecData, 20, 4);    // 费率4

                        rx.ReceiveResult = MsgResult.RecOk;
                    }
                    else
                    {
                        if (frame == null || frame.RecData == null)
                            rx.ReceiveResult = MsgResult.RecTimeout;
                        else
                            rx.ReceiveResult = MsgResult.RecErr;
                    }
                }
            });
            return cmd;
        }
        /// <summary>
        /// 读取第四象限无功电能
        /// </summary>
        /// <param name="dataCol">仪表数据集</param>
        /// <returns></returns>
        public Dlt645Command ReadQuadrantIVkVarh(Device dataCol)
        {
            Dlt645Command cmd = new Dlt645Command(dataCol.ChannelId,dataCol.Id, "第四象限无功电能");
            cmd.Sendframe = new dlt645Frame(dataCol.Address, 0x0008FF00, 0x11);
            cmd.DealReceiveMsg = new EventHandler((Rxcmd, y) =>
            {
                Dlt645Command rx = Rxcmd as Dlt645Command;
                if (rx != null)
                {
                    dlt645Frame frame = BufferToFrame(rx.ReceiveBytes);
                    if (null != frame && frame.RecData.Length > 20)
                    {
                        //dataCol.SN00080000 = 0.01f * BytesToBCD(frame.RecData, 4, 4);     // 第四象限无功电能
                        //dataCol.SN00080001 = 0.01f * BytesToBCD(frame.RecData, 8, 4);     // 费率1
                        //dataCol.SN00080002 = 0.01f * BytesToBCD(frame.RecData, 12, 4);    // 费率2
                        //dataCol.SN00080003 = 0.01f * BytesToBCD(frame.RecData, 16, 4);    // 费率3
                        //dataCol.SN00080004 = 0.01f * BytesToBCD(frame.RecData, 20, 4);    // 费率4

                        rx.ReceiveResult = MsgResult.RecOk;
                    }
                    else
                    {
                        if (frame == null || frame.RecData == null)
                            rx.ReceiveResult =  MsgResult.RecTimeout;
                        else
                            rx.ReceiveResult = MsgResult.RecErr;
                    }
                }
            });
            return cmd;
        }
        /// <summary>
        /// 读取电压
        /// </summary>
        /// <param name="dataCol">仪表数据集</param>
        /// <returns></returns>
        public Dlt645Command ReadVoltage(Device dataCol)
        {
            Dlt645Command cmd = new Dlt645Command(dataCol.ChannelId,dataCol.Id, "电压");
            cmd.Sendframe = new dlt645Frame(dataCol.Address, 0x0201FF00, 0x11);
            cmd.DealReceiveMsg = new EventHandler((rxcmd, y) =>
            {
                Dlt645Command rx = rxcmd as Dlt645Command;
                if (rx != null)
                {
                    var len = 10;

                    if (rx.ReceiveBytes == null || rx.ReceiveBytes.Length == 0)
                    {
                        dataCol.IsConnected = false;
                    }
                    else
                    {
                        dataCol.IsConnected = true;
                    }
                    dlt645Frame frame = BufferToFrame(rx.ReceiveBytes);
                    if (null != frame && frame.RecData.Length >= len)
                    {
                        _dlt645DataMap.Ua = 0.1f * BytesToBcd(frame.RecData, 4, 2);     // A相电压
                        _dlt645DataMap.Ub = 0.1f * BytesToBcd(frame.RecData, 6, 2);    // B
                        _dlt645DataMap.Uc = 0.1f * BytesToBcd(frame.RecData, 8, 2);    // C

                        rx.ReceiveResult = MsgResult.RecOk;
                    }
                    else
                    {
                        if (frame == null || frame.RecData == null)
                            rx.ReceiveResult = MsgResult.RecTimeout;
                        else
                            rx.ReceiveResult = MsgResult.RecErr;
                    }
                }
            });
            return cmd;
        }
        /// <summary>
        /// 读取电流
        /// </summary>
        /// <param name="dataCol">仪表数据集</param>
        /// <returns></returns>
        public Dlt645Command ReadCurrent(Device dataCol)
        {
            Dlt645Command cmd = new Dlt645Command(dataCol.ChannelId,dataCol.Id, "电流");
            cmd.Sendframe = new dlt645Frame(dataCol.Address, 0x0202FF00, 0x11);
            cmd.DealReceiveMsg = new EventHandler((rxcmd, y) =>
            {
                Dlt645Command rx = rxcmd as Dlt645Command;
                if (rx != null)
                {
                    int len = 13;

                    if (rx.ReceiveBytes == null || rx.ReceiveBytes.Length == 0) // 通信中断
                    {
                        dataCol.IsConnected = false;
                    }
                    else
                    {
                        dataCol.IsConnected = true;
                    }
                    dlt645Frame frame = BufferToFrame(rx.ReceiveBytes);
                    if (null != frame && frame.RecData.Length >= len)
                    {
                        _dlt645DataMap.Ia = 0.001f * BytesToBcd(frame.RecData, 4, 3);     // A相电流
                        _dlt645DataMap.Ib = 0.001f * BytesToBcd(frame.RecData, 7, 3);    // B
                        _dlt645DataMap.Ic = 0.001f * BytesToBcd(frame.RecData, 10, 3);    // C
                        rx.ReceiveResult = MsgResult.RecOk;
                    }
                    else
                    {
                        if (frame == null || frame.RecData == null)
                            rx.ReceiveResult =  MsgResult.RecTimeout;
                        else
                            rx.ReceiveResult = MsgResult.RecErr;
                    }
                }
            });
            return cmd;
        }
        /// <summary>
        /// 读取瞬时有功功率
        /// </summary>
        /// <param name="dataCol">仪表数据集</param>
        /// <returns></returns>
        public Dlt645Command ReadInstantPowerkW(Device dataCol)
        {
            Dlt645Command cmd = new Dlt645Command(dataCol.ChannelId,dataCol.Id, "瞬时有功功率");
            cmd.Sendframe = new dlt645Frame(dataCol.Address, 0x0203FF00, 0x11);
            cmd.DealReceiveMsg = new EventHandler((rxcmd, y) =>
            {
                Dlt645Command rx = rxcmd as Dlt645Command;
                if (rx != null)
                {
                    int len = 16;

                    dlt645Frame frame = BufferToFrame(rx.ReceiveBytes);
                    if (null != frame && frame.RecData.Length >= len)
                    {
                        _dlt645DataMap.Psum = 0.0001f * BytesToBcdWithFlag(frame.RecData, 4, 3);     // 瞬时总有功功率
                        _dlt645DataMap.Pa = 0.0001f * BytesToBcdWithFlag(frame.RecData, 7, 3);    // A
                        _dlt645DataMap.Pb = 0.0001f * BytesToBcdWithFlag(frame.RecData, 10, 3);   // B
                        _dlt645DataMap.Pc = 0.0001f * BytesToBcdWithFlag(frame.RecData, 13, 3);   // C

                        rx.ReceiveResult = MsgResult.RecOk;
                    }
                    else
                    {
                        if (frame == null || frame.RecData == null)
                            rx.ReceiveResult =  MsgResult.RecTimeout;
                        else
                            rx.ReceiveResult = MsgResult.RecErr;
                    }
                }
            });
            return cmd;
        }
        /// <summary>
        /// 读取瞬时无功功率
        /// </summary>
        /// <param name="dataCol">仪表数据集</param>
        /// <returns></returns>
        public Dlt645Command ReadInstantPowerkVar(Device dataCol)
        {
            Dlt645Command cmd = new Dlt645Command(dataCol.ChannelId,dataCol.Id, "瞬时无功功率");
            cmd.Sendframe = new dlt645Frame(dataCol.Address, 0x0204FF00, 0x11);
            cmd.DealReceiveMsg = new EventHandler((rxcmd, y) =>
            {
                Dlt645Command rx = rxcmd as Dlt645Command;
                if (rx != null)
                {
                    int len = 16;

                    dlt645Frame frame = BufferToFrame(rx.ReceiveBytes);
                    if (null != frame && frame.RecData.Length >= len)
                    {
                        _dlt645DataMap.Qsum = 0.0001f * BytesToBcdWithFlag(frame.RecData, 4, 3);     // 瞬时总无功功率
                        _dlt645DataMap.Qa = 0.0001f * BytesToBcdWithFlag(frame.RecData, 7, 3);    // A
                        _dlt645DataMap.Qb = 0.0001f * BytesToBcdWithFlag(frame.RecData, 10, 3);   // B
                        _dlt645DataMap.Qc = 0.0001f * BytesToBcdWithFlag(frame.RecData, 13, 3);   // C

                        rx.ReceiveResult = MsgResult.RecOk;
                    }
                    else
                    {
                        if (frame == null || frame.RecData == null)
                            rx.ReceiveResult =  MsgResult.RecTimeout;
                        else
                            rx.ReceiveResult = MsgResult.RecErr;
                    }
                }
            });
            return cmd;
        }
        /// <summary>
        /// 读取瞬时视在功率
        /// </summary>
        /// <param name="dataCol">仪表数据集</param>
        /// <returns></returns>
        public Dlt645Command ReadInstantPowerKva(Device dataCol)
        {
            Dlt645Command cmd = new Dlt645Command(dataCol.ChannelId,dataCol.Id, "瞬时视在功率");
            cmd.Sendframe = new dlt645Frame(dataCol.Address, 0x0205FF00, 0x11);
            cmd.DealReceiveMsg = new EventHandler((rxcmd, y) =>
            {
                Dlt645Command rx = rxcmd as Dlt645Command;
                if (rx != null)
                {
                    int len = 16;

                    dlt645Frame frame = BufferToFrame(rx.ReceiveBytes);
                    if (null != frame && frame.RecData.Length >= len)
                    {
                        _dlt645DataMap.Ssum = 0.0001f * BytesToBcd(frame.RecData, 4, 3);     // 瞬时总视在功率

                        _dlt645DataMap.Sa = 0.0001f * BytesToBcd(frame.RecData, 7, 3);    // A
                        _dlt645DataMap.Sb = 0.0001f * BytesToBcd(frame.RecData, 10, 3);   // B
                        _dlt645DataMap.Sc = 0.0001f * BytesToBcd(frame.RecData, 13, 3);   // C

                        rx.ReceiveResult = MsgResult.RecOk;
                    }
                    else
                    {
                        if (frame == null || frame.RecData == null)
                            rx.ReceiveResult =  MsgResult.RecTimeout;
                        else
                            rx.ReceiveResult = MsgResult.RecErr;
                    }
                }
            });
            return cmd;
        }
        /// <summary>
        /// 读取瞬时功率因数
        /// </summary>
        /// <param name="dataCol">仪表数据集</param>
        /// <returns></returns>
        public Dlt645Command ReadInstantPowerFactor(Device dataCol)
        {
            Dlt645Command cmd = new Dlt645Command(dataCol.ChannelId,dataCol.Id, "瞬时功率因数");
            cmd.Sendframe = new dlt645Frame(dataCol.Address, 0x0206FF00, 0x11);
            cmd.DealReceiveMsg = new EventHandler((rxcmd, y) =>
            {
                Dlt645Command rx = rxcmd as Dlt645Command;
                if (rx != null)
                {
                    var len = 12;

                    dlt645Frame frame = BufferToFrame(rx.ReceiveBytes);
                    if (null != frame && frame.RecData.Length >= len)
                    {
                        _dlt645DataMap.PFsum = 0.001f * BytesToBcd(frame.RecData, 4, 2);     // 瞬时功率因数

                        _dlt645DataMap.PFa = 0.001f * BytesToBcd(frame.RecData, 6, 2);    // A
                        _dlt645DataMap.PFb = 0.001f * BytesToBcd(frame.RecData, 8, 2);   // B
                        _dlt645DataMap.PFc = 0.001f * BytesToBcd(frame.RecData, 10, 2);   // C

                        rx.ReceiveResult = MsgResult.RecOk;
                    }
                    else
                    {
                        if (frame == null || frame.RecData == null)
                            rx.ReceiveResult =  MsgResult.RecTimeout;
                        else
                            rx.ReceiveResult = MsgResult.RecErr;
                    }
                }
            });
            return cmd;
        }
        /// <summary>
        /// 读取零线电流
        /// </summary>
        /// <param name="dataCol">仪表数据集</param>
        /// <returns></returns>
        public Dlt645Command ReadZeroCurrent(Device dataCol)
        {
            Dlt645Command cmd = new Dlt645Command(dataCol.ChannelId,dataCol.Id, "零线电流");
            cmd.Sendframe = new dlt645Frame(dataCol.Address, 0x02800001, 0x11);
            cmd.DealReceiveMsg = new EventHandler((rxcmd, y) =>
            {
                Dlt645Command rx = rxcmd as Dlt645Command;
                if (rx != null)
                {
                    dlt645Frame frame = BufferToFrame(rx.ReceiveBytes);
                    if (null != frame && frame.RecData.Length >= 7)
                    {
                        //_dlt645DataMap.I0 = 0.001f * BytesToBcd(frame.RecData, 4, 3);     // 零线电流
                        rx.ReceiveResult = MsgResult.RecOk;
                    }
                    else
                    {
                        if (frame == null || frame.RecData == null)
                            rx.ReceiveResult =  MsgResult.RecTimeout;
                        else
                            rx.ReceiveResult = MsgResult.RecErr;
                    }
                }
            });
            return cmd;
        }
        /// <summary>
        /// 读取电网频率
        /// </summary>
        /// <param name="dataCol">仪表数据集</param>
        /// <returns></returns>
        public Dlt645Command ReadFrequency(Device dataCol)
        {
            Dlt645Command cmd = new Dlt645Command(dataCol.ChannelId,dataCol.Id, "电网频率");
            cmd.Sendframe = new dlt645Frame(dataCol.Address, 0x02800002, 0x11);
            cmd.DealReceiveMsg = new EventHandler((rxcmd, y) =>
            {
                Dlt645Command rx = rxcmd as Dlt645Command;
                if (rx != null)
                {
                    dlt645Frame frame = BufferToFrame(rx.ReceiveBytes);
                    if (null != frame && frame.RecData.Length >= 6)
                    {
                        _dlt645DataMap.Freq = 0.01f * BytesToBcd(frame.RecData, 4, 2);     // 电网频率
                        rx.ReceiveResult = MsgResult.RecOk;
                    }
                    else
                    {
                        if (frame == null || frame.RecData == null)
                            rx.ReceiveResult =  MsgResult.RecTimeout;
                        else
                            rx.ReceiveResult = MsgResult.RecErr;
                    }
                }
            });
            return cmd;
        }

        /// <summary>
        /// 读取当前有功需量
        /// </summary>
        /// <param name="dataCol">仪表数据集</param>
        /// <returns></returns>
        public Dlt645Command ReadCurPowerNeedkW(Device dataCol)
        {
            Dlt645Command cmd = new Dlt645Command(dataCol.ChannelId,dataCol.Id, "当前有功需量");
            cmd.Sendframe = new dlt645Frame(dataCol.Address, 0x02800004, 0x11);
            cmd.DealReceiveMsg = new EventHandler((rxcmd, y) =>
            {
                Dlt645Command rx = rxcmd as Dlt645Command;
                if (rx != null)
                {
                    dlt645Frame frame = BufferToFrame(rx.ReceiveBytes);
                    if (null != frame && frame.RecData.Length >= 7)
                    {
                        _dlt645DataMap.Pcur = 0.0001f * BytesToBcd(frame.RecData, 4, 3);     // 当前有功需量
                        rx.ReceiveResult = MsgResult.RecOk;
                    }
                    else
                    {
                        if (frame == null || frame.RecData == null)
                            rx.ReceiveResult =  MsgResult.RecTimeout;
                        else
                            rx.ReceiveResult = MsgResult.RecErr;
                    }
                }
            });
            return cmd;
        }
        /// <summary>
        /// 读取当前无功需量
        /// </summary>
        /// <param name="dataCol">仪表数据集</param>
        /// <returns></returns>
        public Dlt645Command ReadCurPowerNeedkVar(Device dataCol)
        {
            Dlt645Command cmd = new Dlt645Command(dataCol.ChannelId,dataCol.Id, "当前无功需量");
            cmd.Sendframe = new dlt645Frame(dataCol.Address, 0x02800005, 0x11);
            cmd.DealReceiveMsg = new EventHandler((rxcmd, y) =>
            {
                Dlt645Command rx = rxcmd as Dlt645Command;
                if (rx != null)
                {
                    dlt645Frame frame = BufferToFrame(rx.ReceiveBytes);
                    if (null != frame && frame.RecData.Length >= 7)
                    {
                        //_dlt645DataMap.Qcur = 0.0001f * BytesToBcd(frame.RecData, 4, 3);     // 当前无功需量
                        rx.ReceiveResult = MsgResult.RecOk;
                    }
                    else
                    {
                        if (frame == null || frame.RecData == null)
                            rx.ReceiveResult =  MsgResult.RecTimeout;
                        else
                            rx.ReceiveResult = MsgResult.RecErr;
                    }
                }
            });
            return cmd;
        }
        /// <summary>
        /// 读取当前视在需量
        /// </summary>
        /// <param name="dataCol">仪表数据集</param>
        /// <returns></returns>
        public Dlt645Command ReadCurPowerNeedKva(Device dataCol)
        {
            Dlt645Command cmd = new Dlt645Command(dataCol.ChannelId,dataCol.Id, "当前视在需量");
            cmd.Sendframe = new dlt645Frame(dataCol.Address, 0x02800006, 0x11);
            cmd.DealReceiveMsg = new EventHandler((rxcmd, y) =>
            {
                Dlt645Command rx = rxcmd as Dlt645Command;
                if (rx != null)
                {
                    dlt645Frame frame = BufferToFrame(rx.ReceiveBytes);
                    if (null != frame && frame.RecData.Length >= 7)
                    {
                        //_dlt645DataMap.Scur = 0.0001f * BytesToBcd(frame.RecData, 4, 3);     // 当前视在需量
                        rx.ReceiveResult = MsgResult.RecOk;
                    }
                    else
                    {
                        if (frame == null || frame.RecData == null)
                            rx.ReceiveResult =  MsgResult.RecTimeout;
                        else
                            rx.ReceiveResult = MsgResult.RecErr;
                    }
                }
            });
            return cmd;
        }


        ///////////////////////////////以下为写命令/////////////////////////////////////
        /// <summary>
        /// 广播校时一天只能广播校时一次 且时间误差在5分钟内
        /// </summary>
        /// <param name="dt">时间</param>
        /// <returns></returns>
        public Dlt645Command BroadcastSetTime(DateTime dt)
        {
            Dlt645Command cmd = new Dlt645Command("0",0.ToString(), "广播校时");
            List<byte> writeList = new List<byte>();
            writeList.Add((byte)dt.Second);
            writeList.Add((byte)dt.Minute);
            writeList.Add((byte)dt.Hour);
            writeList.Add((byte)dt.Day);
            writeList.Add((byte)dt.Month);
            writeList.Add((byte)(dt.Year - 2000));
            cmd.Sendframe = new dlt645Frame(0x999999999999, 0x08, writeList.ToArray());
            cmd.DealReceiveMsg = null;// 广播校时没有应答,每天只允许一次
            return cmd;
        }
        /// <summary>
        ///  设置日期
        /// </summary>
        /// <param name="dataCol"></param>
        /// <param name="dt"></param>
        /// <returns></returns>
        public Dlt645Command SetDate(Device dataCol, DateTime dt)
        {
            Dlt645Command cmd = new Dlt645Command(dataCol.ChannelId,dataCol.Id, "设置日期");
            List<byte> writeList = new List<byte>();
            writeList.Add(Convert.ToByte(dt.DayOfWeek.ToString("D"), 16));
            writeList.Add(Convert.ToByte(dt.Day.ToString("D"), 16));
            writeList.Add(Convert.ToByte(dt.Month.ToString("D"), 16));
            writeList.Add(Convert.ToByte((dt.Year - 2000).ToString("D"), 16));
            cmd.Sendframe = new dlt645Frame(dataCol.Address, 0x04000101, 0x14, 0, 2, writeList.ToArray());
            cmd.DealReceiveMsg = new EventHandler((rxcmd, y) =>
            {
                Dlt645Command rx = rxcmd as Dlt645Command;
                if (rx != null)
                {
                    dlt645Frame frame = BufferToFrame(rx.ReceiveBytes);
                    if (null != frame && frame.CtrlCode == 0x94)
                    {
                        rx.ReceiveResult = MsgResult.RecOk;
                    }
                    else
                    {
                        if (frame == null || frame.RecData == null)
                            rx.ReceiveResult =  MsgResult.RecTimeout;
                        else
                            rx.ReceiveResult = MsgResult.RecErr;
                    }
                }
            });
            return cmd;
        }
        /// <summary>
        ///  设置时间
        /// </summary>
        /// <param name="dataCol"></param>
        /// <param name="dt"></param>
        /// <returns></returns>
        public Dlt645Command SetTime(Device dataCol, DateTime dt)
        {
            Dlt645Command cmd = new Dlt645Command(dataCol.ChannelId,dataCol.Id, "设置时间");
            List<byte> writeList = new List<byte>();
            writeList.Add(Convert.ToByte(dt.Second.ToString("D"), 16));
            writeList.Add(Convert.ToByte(dt.Minute.ToString("D"), 16));
            writeList.Add(Convert.ToByte(dt.Hour.ToString("D"), 16));
            cmd.Sendframe = new dlt645Frame(dataCol.Address, 0x04000102, 0x14, 0, 2, writeList.ToArray());
            cmd.DealReceiveMsg = new EventHandler((rxcmd, y) =>
            {
                Dlt645Command rx = rxcmd as Dlt645Command;
                if (rx != null)
                {
                    dlt645Frame frame = BufferToFrame(rx.ReceiveBytes);
                    if (null != frame && frame.CtrlCode == 0x94)
                    {
                        rx.ReceiveResult = MsgResult.RecOk;
                    }
                    else
                    {
                        if (frame == null || frame.RecData == null)
                            rx.ReceiveResult =  MsgResult.RecTimeout;
                        else
                            rx.ReceiveResult = MsgResult.RecErr;
                    }
                }
            });
            return cmd;
        }

        /// <summary>
        /// 广播冻结命令
        /// </summary>
        /// <param name="dataCol">仪表数据集</param>
        /// <param name="dt">冻结的时间（只需分时日月有效即可）</param>
        /// <returns></returns>
        public Dlt645Command BroadcastFrozen(Device dataCol, DateTime dt)
        {
            Dlt645Command cmd = new Dlt645Command(dataCol.ChannelId,dataCol.Id, "广播冻结命令");
            List<byte> writeList = new List<byte>();
            writeList.Add((byte)dt.Minute);
            writeList.Add((byte)dt.Hour);
            writeList.Add((byte)dt.Day);
            writeList.Add((byte)dt.Month);
            cmd.Sendframe = new dlt645Frame(0x999999999999, 0x04, writeList.ToArray());
            cmd.DealReceiveMsg = new EventHandler((rxcmd, y) =>
            {
                Dlt645Command rx = rxcmd as Dlt645Command;
                if (rx != null)
                {
                    dlt645Frame frame = BufferToFrame(rx.ReceiveBytes);
                    if (null != frame && frame.CtrlCode == 0x96)
                    {
                        rx.ReceiveResult = MsgResult.RecOk;
                    }
                    else
                    {
                        if (frame == null || frame.RecData == null)
                            rx.ReceiveResult =  MsgResult.RecTimeout;
                        else
                            rx.ReceiveResult = MsgResult.RecErr;
                    }
                }
            });
            return cmd;
        }
        /// <summary>
        ///  普通冻结命令
        /// </summary>
        /// <param name="dataCol">仪表数据集</param>
        /// <param name="dt">冻结的时间（只需分时日月有效即可）</param>
        /// <returns></returns>
        public Dlt645Command GeneralFrozen(Device dataCol, DateTime dt)
        {
            Dlt645Command cmd = new Dlt645Command(dataCol.ChannelId,dataCol.Id, "普通冻结命令");
            List<byte> writeList = new List<byte>();
            writeList.Add((byte)dt.Minute);
            writeList.Add((byte)dt.Hour);
            writeList.Add((byte)dt.Day);
            writeList.Add((byte)dt.Month);
            cmd.Sendframe = new dlt645Frame(dataCol.Address, 0x04, writeList.ToArray());
            cmd.DealReceiveMsg = new EventHandler((rxcmd, y) =>
            {
                Dlt645Command rx = rxcmd as Dlt645Command;
                if (rx != null)
                {
                    dlt645Frame frame = BufferToFrame(rx.ReceiveBytes);
                    if (null != frame && frame.CtrlCode == 0x96)
                    {
                        rx.ReceiveResult = MsgResult.RecOk;
                       
                    }
                    else
                    {
                        if (frame == null || frame.RecData == null)
                            rx.ReceiveResult =  MsgResult.RecTimeout;
                        else
                            rx.ReceiveResult = MsgResult.RecErr;
                   
                    }
                }
            });
            return cmd;
        }
        /// <summary>
        /// 修改当前通信速率
        /// </summary>
        /// <param name="dataCol">仪表数据集</param>
        /// <param name="baudrateZ">波特率特征字</param>
        /// <returns></returns>
        public Dlt645Command SetMeterBaudrate(Device dataCol, byte baudrateZ)
        {
            Dlt645Command cmd = new Dlt645Command(dataCol.ChannelId,dataCol.Id, "修改当前通信速率");
            List<byte> writeList = new List<byte>();
            writeList.Add(baudrateZ);
            cmd.Sendframe = new dlt645Frame(dataCol.Address, 0x17, writeList.ToArray());
            cmd.DealReceiveMsg = new EventHandler((rxcmd, y) =>
            {
                Dlt645Command rx = rxcmd as Dlt645Command;
                if (rx != null)
                {
                    dlt645Frame frame = BufferToFrame(rx.ReceiveBytes);
                    if (null != frame && frame.CtrlCode == 0x97)
                    {
                        rx.ReceiveResult = MsgResult.RecOk;
                    }
                    else
                    {
                        if (frame == null || frame.RecData == null)
                            rx.ReceiveResult =  MsgResult.RecTimeout;
                        else
                            rx.ReceiveResult = MsgResult.RecErr; 
                    }
                }
            });
            return cmd;
        }
        /// <summary>
        /// 修改密码
        /// </summary>
        /// <param name="dataCol">仪表数据集</param>
        /// <param name="operRange">密码权限</param>
        /// <param name="operPwd">原密码或更高权限密码</param>
        /// <param name="newRange">新密码权限</param>
        /// <param name="newPwd">新密码或需设置的密码</param>
        /// <returns></returns>
        public Dlt645Command SetMeterPassword(Device dataCol, byte operRange, UInt32 operPwd, byte newRange, UInt32 newPwd)
        {
            Dlt645Command cmd = new Dlt645Command(dataCol.ChannelId,dataCol.Id, "修改密码");
            List<byte> writeList = new List<byte>();
            UInt32 dataId = (UInt32)(0x04000C01 + newRange);
            writeList.Add(operRange);
            writeList.AddRange(BitConverter.GetBytes(operPwd).Take(3).ToArray());
            writeList.Add(newRange);
            writeList.AddRange(BitConverter.GetBytes(newPwd).Take(3).ToArray());
            cmd.Sendframe = new dlt645Frame(dataCol.Address, 0x18, dataId, writeList.ToArray());
            cmd.DealReceiveMsg = new EventHandler((rxcmd, y) =>
            {
                Dlt645Command rx = rxcmd as Dlt645Command;
                if (rx != null)
                {
                    dlt645Frame frame = BufferToFrame(rx.ReceiveBytes);
                    if (null != frame && frame.CtrlCode == 0x98)
                    {
                        rx.ReceiveResult = MsgResult.RecOk;
                    }
                    else
                    {
                        if (frame == null || frame.RecData == null)
                            rx.ReceiveResult =  MsgResult.RecTimeout;
                        else
                            rx.ReceiveResult = MsgResult.RecErr;
                    }
                }
            });
            return cmd;
        }
        /// <summary>
        /// 最大需量清零
        /// </summary>
        /// <param name="dataCol">仪表数据集</param>
        /// <param name="operRange">密码权限</param>
        /// <param name="operPwd">操作密码</param>
        /// <param name="operatorCode">操作者代码</param>
        /// <returns></returns>
        public Dlt645Command ClearMaxDemand(Device dataCol, byte operRange, UInt32 operPwd, UInt32 operatorCode)
        {
            Dlt645Command cmd = new Dlt645Command(dataCol.ChannelId,dataCol.Id, "最大需量清零");
            List<byte> writeList = new List<byte>();
            writeList.Add(operRange);
            writeList.AddRange(BitConverter.GetBytes(operPwd).Take(3).ToArray());
            writeList.AddRange(BitConverter.GetBytes(operatorCode).ToArray());
            cmd.Sendframe = new dlt645Frame(dataCol.Address, 0x19, writeList.ToArray());
            cmd.DealReceiveMsg = new EventHandler((rxcmd, y) =>
            {
                Dlt645Command rx = rxcmd as Dlt645Command;
                if (rx != null)
                {
                    dlt645Frame frame = BufferToFrame(rx.ReceiveBytes);
                    if (null != frame && frame.CtrlCode == 0x99)
                    {
                        rx.ReceiveResult = MsgResult.RecOk;
                    }
                    else
                    {
                        if (frame == null || frame.RecData == null)
                            rx.ReceiveResult =  MsgResult.RecTimeout;
                        else
                            rx.ReceiveResult = MsgResult.RecErr;
                    }
                }
            });
            return cmd;
        }
        /// <summary>
        /// 最大需量清零(使用数据集中的密码)
        /// </summary>
        /// <param name="dataCol">仪表数据集</param>
        /// <returns></returns>
        public Dlt645Command ClearMaxDemand(Device dataCol)
        {
            Dlt645Command cmd = new Dlt645Command(dataCol.ChannelId,dataCol.Id, "最大需量清零");
            List<byte> writeList = new List<byte>();
           // todo
           // writeList.Add(dataCol.OperRange);
           // writeList.AddRange(BitConverter.GetBytes(dataCol.OperPwd).Take(3).ToArray());
           // writeList.AddRange(BitConverter.GetBytes(dataCol.OperCode).ToArray());
            cmd.Sendframe = new dlt645Frame(dataCol.Address, 0x19, writeList.ToArray());
            cmd.DealReceiveMsg = new EventHandler((rxcmd, y) =>
            {
                Dlt645Command rx = rxcmd as Dlt645Command;
                if (rx != null)
                {
                    dlt645Frame frame = BufferToFrame(rx.ReceiveBytes);
                    if (null != frame && frame.CtrlCode == 0x99)
                    {
                        rx.ReceiveResult = MsgResult.RecOk;
                    }
                    else
                    {
                        if (frame == null || frame.RecData == null)
                            rx.ReceiveResult =  MsgResult.RecTimeout;
                        else
                            rx.ReceiveResult = MsgResult.RecErr;
                    }
                }
            });
            return cmd;
        }
        /// <summary>
        /// 电表清零（清空表内电能、最大需量、冻结量、事件记录、负荷记录等数据）
        /// </summary>
        /// <param name="dataCol">仪表数据集</param>
        /// <param name="operRange">密码权限</param>
        /// <param name="operPwd">操作密码</param>
        /// <param name="operatorCode">操作者代码</param>
        /// <returns></returns>
        public Dlt645Command ClearMeterData(Device dataCol, byte operRange, UInt32 operPwd, UInt32 operatorCode)
        {
            Dlt645Command cmd = new Dlt645Command(dataCol.ChannelId,dataCol.Id, "电表清零");
            List<byte> writeList = new List<byte>();
            writeList.Add(operRange);
            writeList.AddRange(BitConverter.GetBytes(operPwd).Take(3).ToArray());
            writeList.AddRange(BitConverter.GetBytes(operatorCode).ToArray());
            cmd.Sendframe = new dlt645Frame(dataCol.Address, 0x1A, writeList.ToArray());
            cmd.DealReceiveMsg = new EventHandler((rxcmd, y) =>
            {
                Dlt645Command rx = rxcmd as Dlt645Command;
                if (rx != null)
                {
                    dlt645Frame frame = BufferToFrame(rx.ReceiveBytes);
                    if (null != frame && frame.CtrlCode == 0x9A)
                    {
                        rx.ReceiveResult = MsgResult.RecOk;
                    }
                    else
                    {
                        if (frame == null || frame.RecData == null)
                            rx.ReceiveResult =  MsgResult.RecTimeout;
                        else
                            rx.ReceiveResult = MsgResult.RecErr;
                    }
                }
            });
            return cmd;
        }
        /// <summary>
        /// 电表清零（清空表内电能最大需量冻结量事件记录负荷记录等数据）
        /// </summary>
        /// <param name="dataCol">仪表数据集</param>
        /// <returns></returns>
        public Dlt645Command ClearMeterData(Device dataCol)
        {
            Dlt645Command cmd = new Dlt645Command(dataCol.ChannelId,dataCol.Id, "电表清零");
            List<byte> writeList = new List<byte>();
            //todo
            //writeList.Add(dataCol.OperRange);
            //writeList.AddRange(BitConverter.GetBytes(dataCol.OperPwd).Take(3).ToArray());
            //writeList.AddRange(BitConverter.GetBytes(dataCol.OperCode).ToArray());
            cmd.Sendframe = new dlt645Frame(dataCol.Address, 0x1A, writeList.ToArray());
            cmd.DealReceiveMsg = new EventHandler((rxcmd, y) =>
            {
                Dlt645Command rx = rxcmd as Dlt645Command;
                if (rx != null)
                {
                    dlt645Frame frame = BufferToFrame(rx.ReceiveBytes);
                    if (null != frame && frame.CtrlCode == 0x9A)
                    {
                        rx.ReceiveResult = MsgResult.RecOk;
                    }
                    else
                    {
                        if (frame == null || frame.RecData == null)
                            rx.ReceiveResult =  MsgResult.RecTimeout;
                        else
                            rx.ReceiveResult = MsgResult.RecErr;
                    }
                }
            });
            return cmd;
        }
        /// <summary>
        /// 事件总清零
        /// </summary>
        /// <param name="dataCol">仪表数据集</param>
        /// <returns></returns>
        public Dlt645Command ClearAllMeterEvent(Device dataCol)
        {
            Dlt645Command cmd = new Dlt645Command(dataCol.ChannelId,dataCol.Id, "事件总清零");
            List<byte> writeList = new List<byte>();
            //todo
            //writeList.Add(dataCol.OperRange);
            //writeList.AddRange(BitConverter.GetBytes(dataCol.OperPwd).Take(3).ToArray());
            //writeList.AddRange(BitConverter.GetBytes((UInt32)dataCol.OperCode).ToArray());
            //writeList.AddRange(new byte[] { 0xFF, 0xFF, 0xFF, 0xFF });
            cmd.Sendframe = new dlt645Frame(dataCol.Address, 0x1B, writeList.ToArray());
            cmd.DealReceiveMsg = new EventHandler((rxcmd, y) =>
            {
                Dlt645Command rx = rxcmd as Dlt645Command;
                if (rx != null)
                {
                    dlt645Frame frame = BufferToFrame(rx.ReceiveBytes);
                    if (null != frame && frame.CtrlCode == 0x9B)
                    {
                        rx.ReceiveResult = MsgResult.RecOk;
                    }
                    else
                    {
                        if (frame == null || frame.RecData == null)
                            rx.ReceiveResult =  MsgResult.RecTimeout;
                        else
                            rx.ReceiveResult = MsgResult.RecErr;
                    }
                }
            });
            return cmd;
        }
        /// <summary>
        /// 分项事件清零
        /// </summary>
        /// <param name="dataCol">仪表数据集</param>
        /// <param name="dataId">数据项ID</param>
        /// <returns></returns>
        public Dlt645Command ClearMeterEvent(Device dataCol, UInt32 dataId)
        {
            Dlt645Command cmd = new Dlt645Command(dataCol.ChannelId,dataCol.Id, "分项事件清零");
            List<byte> writeList = new List<byte>();
            //writeList.Add(dataCol.OperRange);
            //writeList.AddRange(BitConverter.GetBytes(dataCol.OperPwd).Take(3).ToArray());
            //writeList.AddRange(BitConverter.GetBytes(dataCol.OperCode).ToArray());
            //writeList.AddRange(BitConverter.GetBytes(0xFF000000 | dataId).ToArray());
            cmd.Sendframe = new dlt645Frame(dataCol.Address, 0x1B, writeList.ToArray());
            cmd.DealReceiveMsg = new EventHandler((rxcmd, y) =>
            {
                Dlt645Command rx = rxcmd as Dlt645Command;
                if (rx != null)
                {
                    dlt645Frame frame = BufferToFrame(rx.ReceiveBytes);
                    if (null != frame && frame.CtrlCode == 0x9B)
                    {
                        rx.ReceiveResult = MsgResult.RecOk;
                    }
                    else
                    {
                        if (frame == null || frame.RecData == null)
                            rx.ReceiveResult =  MsgResult.RecTimeout;
                        else
                            rx.ReceiveResult = MsgResult.RecErr;
                    }
                }
            });
            return cmd;
        }
        #region 命令提交

        /// <summary>
        /// 执行命令
        /// </summary>
        /// <param name="operid">命令Id</param>
        /// <returns></returns>
        public override RxTxCommand PostToExcute(string operid)
        {
            if (Operations.ContainsKey(operid))
            {
                Operation oper = DealOperationWithPara(Operations[operid], null); // 处理地址
                RxTxCommand cmd = new RxTxCommand(Dev.ChannelId, Dev.Id, oper.Name);
                cmd.IsAscii = oper.IsAscii;
                cmd.SendBytes = oper.MsgBuffer;
                cmd.NeedReply = oper.NeedReply;
                cmd.Timeout = oper.Timeout;
                cmd.DealReceiveMsg += Cmd_DealReceiveMsg;
                return cmd;
            }
            else
            {
                return null;
            }
        }

        /// <summary>
        /// 带参数执行命令
        /// </summary>
        /// <param name="operid">命令Id</param>
        /// <param name="paras">参数集合</param>
        /// <returns></returns>
        public override RxTxCommand PostToExcute(string operid, string[] paras)
        {
            if (Operations.ContainsKey(operid))
            {
                Operation oper = DealOperationWithPara(Operations[operid], paras);
                RxTxCommand cmd = new RxTxCommand(Dev.ChannelId, Dev.Id, oper.Name);
                cmd.IsAscii = oper.IsAscii;
                cmd.NeedReply = oper.NeedReply;
                cmd.Timeout = oper.Timeout;
                cmd.SendBytes = oper.MsgBuffer;
                cmd.DealReceiveMsg += Cmd_DealReceiveMsg;
                return cmd;
            }
            else
            {
                return null;
            }
        }

        private void Cmd_DealReceiveMsg(object sender, EventArgs e)
        {
            RxTxCommand cmd = sender as RxTxCommand;
            if (cmd != null)
            {
                Console.WriteLine("接收:" + cmd.ReceiveMsg);
            }
        }

        #endregion

        #region 数据项额外参数处理

        public override List<DataItem> DeSerializeDataItems(List<DataItem> items)
        {
            items = DeSerialize<Dlt645TagObject>(items);
            return items;
        }
        public override DataItem DeSerializeDataItem(DataItem item)
        {
            item = DeSerialize<Dlt645TagObject>(item);
            return item;
        }
        public override DataItem DecorateItem(DataItem item)
        {
            item.TagObject = new Dlt645TagObject();
            return item;
        }

        #endregion

        public override RxTxCommand WriteValue(string dataId, double value)
        {
            return null;
        }

        public override RxTxCommand WriteValue(string startId, byte[] buffer)
        {
            return null;
        }
    }

}
